﻿
using helloworld.Common;
using helloworld.DI;
using helloworld.File;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Primitives;
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;

namespace helloworld
{
    public class Program
    {
        static void Main1(string[] args) => new WebHostBuilder()
                 .UseKestrel()
                 .UseStartup<Startup>()
                 .UseContentRoot(Directory.GetCurrentDirectory())
                 .UseUrls("http://localhost:60001", "http://localhost:60002")
                 .Build()
                 .Run();

        static void MainIOC(string[] args)
        {
            //IServiceCollection services = new ServiceCollection()
            //    .AddSingleton<IFoo, Foo>()
            //    .AddSingleton<IBar>(new Bar())
            //    .AddSingleton<IBaz>(_ => new Baz())
            //    .AddSingleton<IGux, Gux>();

            //IServiceProvider serviceProvider = services.BuildServiceProvider();
            //Console.WriteLine($@"serviceProvider.GetService<IFoo>:{serviceProvider.GetService<IFoo>()}");
            //Console.WriteLine($@"serviceProvider.GetService<IBar>:{serviceProvider.GetService<IBar>()}");
            //Console.WriteLine($@"serviceProvider.GetService<IBaz>:{serviceProvider.GetService<IBaz>()}");
            //Console.WriteLine($@"serviceProvider.GetService<IGux>:{serviceProvider.GetService<IGux>()}");

            //==================================

            //IServiceCollection services = new ServiceCollection()
            //    .AddSingleton<IFooBar, Foo>()
            //    .AddSingleton<IFooBar, Bar>();

            //IServiceProvider serviceProvider = services.BuildServiceProvider();
            //Console.WriteLine($@"serviceProvider.GetServices<IFooBar>:{serviceProvider.GetService<IFooBar>()}");

            //IEnumerable<IFooBar> serviceInstances = serviceProvider.GetServices<IFooBar>();

            //int index = 1;
            //Console.WriteLine("serviceProvider.GetServices<IFooBar>:");

            //foreach (var serviceInstance in serviceInstances)
            //{
            //    Console.WriteLine($@"{index++}:{serviceInstance}");
            //}

            //====================================

            //IServiceCollection services = new ServiceCollection();

            //IServiceProvider serviceProvider = services.BuildServiceProvider();

            //Debug.Assert(object.ReferenceEquals(serviceProvider, serviceProvider.GetService<IServiceProvider>()));

            //Debug.Assert(object.ReferenceEquals(serviceProvider, serviceProvider.GetServices<IServiceProvider>().Single()));

            //========================================

            //IServiceProvider serviceProvider = new ServiceCollection()
            //    .AddTransient<IFoo, Foo>()
            //    .AddTransient<IBaz, Baz>()
            //    .AddTransient(typeof(IFooBaz<,>), typeof(FooBaz<,>))
            //    .BuildServiceProvider();

            //Console.WriteLine($@"serviceProvider.GetService<IFooBaz<IFoo, IBaz>>().Foo:{serviceProvider.GetService<IFooBaz<IFoo, IBaz>>().Foo}");
            //Console.WriteLine($@"serviceProvider.GetService<IFooBaz<IFoo, IBaz>>().Baz:{serviceProvider.GetService<IFooBaz<IFoo, IBaz>>().Baz}");

            //=======================================

            //var serviceInstanceName = new ServiceCollection()
            //    .AddSingleton<IFoo, Foo>()
            //    .AddSingleton<IBar, Bar>()
            //    .AddSingleton<IBaz, Baz>()
            //    .AddSingleton<IGux, Gux>()
            //    .BuildServiceProvider()
            //    .GetService<IGux>();

            //Console.WriteLine(serviceInstanceName);

            //===================================

            //IServiceProvider serviceProvider1 = new ServiceCollection().BuildServiceProvider();
            //IServiceProvider serviceProvider2 = serviceProvider1.GetService<IServiceScopeFactory>().CreateScope().ServiceProvider;

            //object root = serviceProvider2.GetType().GetField("_root", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(serviceProvider2);

            //Debug.Assert(object.ReferenceEquals(serviceProvider1, root));

            //=======================
            //IServiceProvider root = new ServiceCollection()
            //    .AddTransient<IFoo, Foo>()
            //    .AddScoped<IBar, Bar>()
            //    .AddSingleton<IBaz, Baz>()
            //    .BuildServiceProvider();

            //IServiceProvider child1 = root.GetService<IServiceScopeFactory>().CreateScope().ServiceProvider;

            //IServiceProvider child2 = root.GetService<IServiceScopeFactory>().CreateScope().ServiceProvider;

            //Console.WriteLine($@"ReferenceEquals(serviceProvider1.GetService<IFoo>(), serviceProvider1.GetService<IFoo>()):{ReferenceEquals(root.GetService<IFoo>(), root.GetService<IFoo>())}");
            //Console.WriteLine($@"ReferenceEquals(child1.GetService<IBar>(),child1.GetService<IBar>()):{ReferenceEquals(child1.GetService<IBar>(), child1.GetService<IBar>())}");
            //Console.WriteLine($@"ReferenceEquals(child1.GetService<IBar>(), child2.GetService<IBar>()):{ReferenceEquals(child1.GetService<IBar>(), child2.GetService<IBar>())}");
            //Console.WriteLine($@"ReferenceEquals(child1.GetService<IBaz>(), child2.GetService<IBaz>()):{ReferenceEquals(child1.GetService<IBaz>(), child2.GetService<IBaz>())}");


            //========================

            //IServiceProvider root = new ServiceCollection()
            //    .AddTransient<IFoo, Foo>()
            //    .AddScoped<IBar, Bar>()
            //    .AddSingleton<IBaz, Baz>()
            //    .BuildServiceProvider();

            //IServiceProvider child1 = root.GetService<IServiceScopeFactory>().CreateScope().ServiceProvider;
            //IServiceProvider child2 = root.GetService<IServiceScopeFactory>().CreateScope().ServiceProvider;

            //child1.GetService<IFoo>();
            //child1.GetService<IFoo>();
            //child2.GetService<IBar>();
            //child2.GetService<IBaz>();

            //Console.WriteLine("child1.Dispose():");
            //((IDisposable)child1).Dispose();

            //Console.WriteLine("child2.Dispose():");
            //((IDisposable)child2).Dispose();

            //Console.WriteLine("root.Dispose():");
            //((IDisposable)root).Dispose();

            //===============================

            //IServiceProvider serviceProvider = new ServiceCollection()
            //    .AddTransient<IFooBar, FooBar>()
            //    .BuildServiceProvider();

            //serviceProvider.GetService<IFooBar>().Dispose();

            //GC.Collect();

            //Console.WriteLine("=================================");

            //ServiceScopeAutoFinalize(serviceProvider);

            //GC.Collect();

            //===========================================


            Console.ReadKey();
        }

        private static void ServiceScopeAutoFinalize(IServiceProvider serviceProvider)
        {
            using (IServiceScope serviceScope = serviceProvider.GetService<IServiceScopeFactory>().CreateScope())
            {
                serviceScope.ServiceProvider.GetService<IFooBar>();
            }
        }

        static void MainCommon(string[] args)
        {

            var service = LimitingFactory.Build(LimitingType.TokenBucket, 500, 200);

            while (true)
            {
                var result = service.Request();
                //如果返回true，说明可以进行业务处理，否则需要继续等待
                if (result)
                {
                    //业务处理......
                    Console.WriteLine("获取成功");
                }
                else
                {
                    Console.WriteLine("获取失败");
                    Thread.Sleep(1);
                }
            }

            Console.ReadKey();
        }

        static void Main(string[] args)
        {
            //new ServiceCollection()
            //    .AddSingleton<IFileProvider>(new PhysicalFileProvider(@"D:\Download\Test"))
            //    .AddSingleton<IFileManager, FileManager>()
            //    .BuildServiceProvider()
            //    .GetService<IFileManager>()
            //    .ShowStructer((layer, name) =>
            //    {
            //        Console.WriteLine("{0}{1}", new string('\t', layer), name);
            //    });


            //IFileProvider fileProvider = new PhysicalFileProvider(@"D:\Download\Test");

            //var fileInfo = fileProvider.GetFileInfo("A");

            //ChangeToken.OnChange(() => fileProvider.Watch("data.txt"),
            //    () => FileManager.LoanFileAsync(fileProvider)
            //);

            //while (true)
            //{
            //    System.IO.File.WriteAllText(@"D:\Download\Test\data.txt", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));

            //    Task.Delay(5000).Wait();
            //}
            //Console.ReadKey();

            //===================
            var num1 = 0;
            Trace.WriteLine(10 / num1);



        }
    }
}
